﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace OpenLS.Spreadsheet.UI.Internals
{
    internal class IconDrawer: IDisposable
    {
        private readonly Rect _rect;
        private readonly DrawingContext _drawingContext;
        DrawingContext Context { get { return _drawingContext; } }

        public IconDrawer(Rect rect, DrawingContext drawingContext)
        {
            _rect = rect;
            _drawingContext = drawingContext;
            drawingContext.PushTransform(new TranslateTransform(_rect.X, _rect.Y + _rect.Height - 15));
        }



        public  void Draw(IconType icon)
        {
            switch (icon)
            {
                case IconType.BlackCircle:
                    DrawCircle(Black);
                    break;
                case IconType.BlackCircleWithBorder:
                    DrawCircle2( Black);
                    break;
                case IconType.BlackCircleWithOneWhiteQuarter:
                    DrawOneQuarter();
                    break;
                case IconType.BlackCircleWithThreeWhiteQuarters:
                    DrawThreeQuarters();
                    break;
                case IconType.BlackCircleWithTwoWhiteQuarters:
                    DrawTwoQuarters();
                    break;
                case IconType.FourFilledBoxes:
                    DrawBox1(Blue);
                    DrawBox2(Blue);
                    DrawBox3(Blue);
                    DrawBox4(Blue);
                    break;
                case IconType.GoldStar:
                    DrawStar(Gold);
                    break;
                case IconType.GrayCircle:
                    DrawCircle(LightGray);
                    break;
                case IconType.GrayDownArrow:
                    DrawDownArrow(LightGray);
                    break;
                case IconType.GrayDownRightArrow:
                    DrawDownRightArrow(LightGray);
                    break;
                case IconType.GrayRightArrow:
                    DrawRightArrow(LightGray);
                    break;
                case IconType.GrayUpArrow:
                    DrawUpArrow(LightGray);
                    break;
                case IconType.GrayUpRightArrow:
                    DrawUpRightArrow(LightGray);
                    break;
                case IconType.GreenCheck:
                    DrawCheck(Green);
                    break;
                case IconType.GreenCheckSymbol:
                    DrawCheckSymbol(Green);
                    break;
                case IconType.GreenCircle:
                    DrawCircle(Green);
                    break;
                case IconType.GreenFlag:
                    DrawFlag(Green);
                    break;
                case IconType.GreenTrafficLight:
                    DrawTrafficLight(Green);
                    break;
                case IconType.GreenUpArrow:
                    DrawUpArrow(Green);
                    break;

                case IconType.GreenUpTriangle:
                    DrawUpTriangle(Green);
                    break;
                case IconType.HalfGoldStar:
                    DrawHalfGoldStar();
                    break;
                case IconType.OneFilledBox:
                    DrawBox1(Blue);
                    DrawBox2(LightGray);
                    DrawBox3(LightGray);
                    DrawBox4(LightGray);
                    break;
                case IconType.PinkCircle:
                    DrawCircle(Pink);
                    break;
                case IconType.RedCircle:
                    DrawCircle(Red);
                    break;
                case IconType.RedCircleWithBorder:
                    DrawCircle2(Red);
                    break;
                case IconType.RedCross:
                    DrawCross(Red);
                    break;
                case IconType.RedCrossSymbol:
                    DrawCrossSymbol(Red);
                    break;
                case IconType.RedDiamond:
                    DrawDiamond(Red);
                    break;
                case IconType.RedDownArrow:
                    DrawDownArrow(Red);
                    break;
                case IconType.RedDownTriangle:
                    DrawDownTriangle (Red);
                    break;
                case IconType.RedFlag:
                    DrawFlag((Red));
                    break;
                case IconType.RedTrafficLight:
                    DrawTrafficLight(Red);
                    break;
                case IconType.SignalMeterWithFourFillBars:
                    DrawSignalMeter1(Blue, DarkBlue);
                    DrawSignalMeter2(Blue, DarkBlue);
                    DrawSignalMeter3(Blue, DarkBlue);
                    DrawSignalMeter4(Blue, DarkBlue);
                    break;

                case IconType.SignalMeterWithNoFillBar:
                    DrawSignalMeter1(LightGray, Gray);
                    DrawSignalMeter2(LightGray, Gray);
                    DrawSignalMeter3(LightGray, Gray);
                    DrawSignalMeter4(LightGray, Gray);
                    break;
                case IconType.SignalMeterWithOneFillBar:
                    DrawSignalMeter1(Blue, DarkBlue);
                    DrawSignalMeter2(LightGray, Gray);
                    DrawSignalMeter3(LightGray, Gray);
                    DrawSignalMeter4(LightGray, Gray);
                    break;
                case IconType.SignalMeterWithThreeFillBars:
                    DrawSignalMeter1(Blue, DarkBlue);
                    DrawSignalMeter2(Blue, DarkBlue);
                    DrawSignalMeter3(Blue, DarkBlue);
                    DrawSignalMeter4(LightGray, Gray);
                    break;
                case IconType.SignalMeterWithTwoFillBars:
                    DrawSignalMeter1(Blue, DarkBlue);
                    DrawSignalMeter2(Blue, DarkBlue);
                    DrawSignalMeter3(LightGray, Gray);
                    DrawSignalMeter4(LightGray, Gray);
                    break;
                case IconType.SilverStar:
                    DrawStar(Silver);
                    break;
                case IconType.ThreeFilledBoxes:
                    DrawBox1(Blue);
                    DrawBox2(Blue);
                    DrawBox3(Blue);
                    DrawBox4(LightGray);
                    break;
                case IconType.TwoFilledBoxes:
                    DrawBox1(Blue);
                    DrawBox2(Blue);
                    DrawBox3(LightGray);
                    DrawBox4(LightGray);
                    break;
                case IconType.WhiteCircleWithBlackBorder:
                    DrawCircleWithBorder(White);
                    break;
                case IconType.YellowCircle:
                    DrawCircle(Yellow);
                    break;
                case IconType.YellowDash:
                    DrawDash(Yellow);
                    break;
                case IconType.YellowDownRightArrow:
                    DrawDownRightArrow(Yellow);
                    break;
                case IconType.YellowExclamation:
                    DrawExclamation(Yellow);
                    break;
                case IconType.YellowExclamationSymbol:
                    DrawExclamationSymbol(Yellow);
                    break;
                case IconType.YellowFlag:
                    DrawFlag(Yellow);
                    break;
                case IconType.YellowRightArrow:
                    DrawRightArrow(Yellow);
                    break;
                case IconType.YellowTrafficLight:
                    DrawTrafficLight(Yellow);
                    break;
                case IconType.YellowTriangle:
                    DrawTrafficLight(Yellow);
                    break;
                case IconType.YellowUpRightArrow:
                    DrawUpRightArrow(Yellow);
                    break;
                case IconType.ZeroFilledBoxes:
                    DrawBox1(LightGray);
                    DrawBox2(LightGray);
                    DrawBox3(LightGray);
                    DrawBox4(LightGray);
                    break;
                default:
                    throw new NotSupportedException();
            }
        }

        protected Brush DarkBlue
        {
            get { return Blue; }
        }

        private void DrawCircleWithBorder(Brush white)
        {
            Context.DrawEllipse(white, new Pen(Brushes.Black, 1), new Point(7, 7),7,7  );
        }

        protected Brush White
        {
            get { return Brushes.White; }
        }

        private void DrawExclamationSymbol(Brush brush)
        {
            DrawPath(brush, 6, 0, 8, 0, 8, 4, 7, 8, 6, 4, 6, 0);
            Context.DrawEllipse(brush, null, new Point(7, 10),2,3 );
        }

        private void DrawExclamation(Brush brush)
        {
            DrawSquare(brush);
        }

        private void DrawDash(Brush brush)
        {
            DrawSquare(brush);
        }

        private void DrawFlag(Brush brush)
        {
            DrawPath(brush, 0, 0, 2, 4, 8, 4, 9, 3, 4, 0, 0, 0);
        }

        private void DrawDownTriangle(Brush brush)
        {
            DrawSquare(brush);
        }

        private void DrawDownRightArrow(Brush brush)
        {
            DrawPath(brush, 3, 0, 11, 8, 15, 4,   15,15, 4,15,  8, 11,  0, 3,  3, 0);
        }

        protected Brush Silver
        {
            get { return Brushes.Silver; }
        }

        private void DrawRightArrow(Brush brush)
        {
            DrawPath(brush, 0, 4,  7, 4,  7, 0,  14, 7,  7, 14,  7, 10, 0, 10, 0, 4);
        }

        private void DrawCheckSymbol(Brush brush)
        {
            DrawPath(new Pen(brush, 1), 0, 0, 6, 8, 14, 14);
        }

        private void DrawCheck(Brush green)
        {
            DrawSquare(green);
        }

        private void DrawTrafficLight(Brush brush)
        {
            Context.DrawRoundedRectangle(Brushes.Black, null, new Rect(0, 0, 14, 14), 1, 1);
            Context.DrawEllipse(brush, null, new Point(7, 7), 7, 7);
        }

        private void DrawUpRightArrow(Brush brush)
        {
            DrawPath(brush, 3,0, 15,0, 15, 11, 11,7, 3,15, 0, 11, 8, 3, 3,0);
        }

        private void DrawDownArrow(Brush brush)
        {
            DrawPath(brush, 4, 0, 4, 7,  0, 7, 7, 14, 14, 7,  10, 7,  10, 0,  4, 0);
        }

        protected Brush Gold
        {
            get { return Brushes.Gold; }
        }

        private void DrawThreeQuarters()
        {
            Context.DrawEllipse(Brushes.Pink, null, new Point(7, 7), 7, 7);
        }

        private void DrawStar(Brush gold)
        {
            DrawSquare(gold);
        }

        private void DrawTwoQuarters()
        {
            Context.DrawEllipse(Brushes.Pink, null, new Point(7, 7), 7, 7);
        }

        private void DrawOneQuarter()
        {
            Context.DrawEllipse(Brushes.Pink, null, new Point(7, 7), 7, 7 );
        }

        protected Brush Yellow
        {
            get { return new LinearGradientBrush(Color.FromRgb(255, 238, 182), Color.FromRgb(253, 211, 61), 45); }
        }

        private void DrawDiamond(Brush red)
        {
            DrawSquare(red);
        }

        private void DrawCrossSymbol(Brush brush)
        {
            DrawCross(brush);
        }

        private void DrawCross(Brush brush)
        {
            DrawPath(brush, 2, 0, 7,5,  12, 0, 14, 2, 9, 7, 14,12,  12, 14,  7, 9,  2, 14,  0, 12,  5, 7,  0, 2,  2,0  );
        }

        protected Brush Red
        {
            get { return Brushes.Red; }
        }

        protected Brush Pink
        {
            get { return Brushes.Pink; }
        }

        private void DrawBox4(Brush o)
        {
            DrawSquare(o);
        }

        private void DrawBox3(Brush o)
        {
            DrawSquare(o);
        }

        protected Brush LightGray
        {
            get { return new SolidColorBrush(Color.FromRgb(212, 213, 213)); }
        }
        Brush Gray { get { return new SolidColorBrush(Color.FromRgb(162, 162, 162)); } }


        private void DrawBox2(Brush o)
        {
            DrawSquare(o);
        }

        protected Brush Blue
        {
            get { return new SolidColorBrush(Color.FromRgb(61, 105, 150)); }
        }

        private void DrawBox1(Brush o)
        {
            DrawSquare(o);
        }

        private void DrawHalfGoldStar()
        {
            DrawSquare(Brushes.Pink);
        }

        private void DrawUpTriangle(Brush brush)
        {
            DrawSquare(brush);
        }

        private void DrawUpArrow(Brush brush)
        {
            DrawPath(brush,             7, 0,
            14, 7,
            10, 7,
            10, 14,
            4, 14,
            4, 7,
            0, 7,
            7, 0);
        }
        void DrawPath(Brush brush, params double[] points)
        {
            DrawPath(brush, DoubleToPoints(points));
        }
        void DrawPath(Pen pen, params double[] points)
        {
            DrawPath(pen, DoubleToPoints(points));
        }
        static IEnumerable<Point> DoubleToPoints(params double[] points)
        {
            for (int i = 0; i < points.Length; i++)
            {
                yield return(new Point(points[i++], points[i]));
            }
            
        }
        void DrawPath(Brush brush, IEnumerable<Point> points)
        {
            PathGeometry pathGeometry = GetGeometry(points);
            Context.DrawGeometry(brush, null, pathGeometry);
        }

        void DrawPath(Pen pen, IEnumerable<Point> points)
        {
            PathGeometry pathGeometry = GetGeometry(points);
            Context.DrawGeometry(null, pen, pathGeometry);
        }

        private static PathGeometry GetGeometry(IEnumerable<Point> points)
        {
            var pathSegments = new List<PathSegment>();
            Point startPoint = new Point();
            Func<Point, Point > f = pt => new Point(pt.X, pt.Y);
            foreach (Point point in points)
            {
                if (pathSegments.Count == 0)
                    startPoint = f (point);
                pathSegments.Add(new LineSegment(f(point), true));
            }
            var pathFigure = new PathFigure(startPoint, pathSegments, true);
            return new PathGeometry(new PathFigure[]{pathFigure});
        }



        private void DrawSquare(Brush brush)
        {
            throw new NotSupportedException();
        }

        protected static Brush Green
        {
            get { return Brushes.Green; }
        }

        private void DrawCircle2(Brush brush)
        {
            Context.DrawEllipse(brush, null, new Point(6, 15 - 6), 6, 6 );
        }

        private void DrawCircle(Brush brush)
        {
            Context.DrawEllipse(brush, null, new Point(6, 15 - 6), 6, 6);
        }

        private static Brush Black
        {
            get { return Brushes.Black; }
        }

        public Rect Rect
        {
            get { return _rect; }
        }

        private const double meterWidth = 2;
        private  void DrawSignalMeter4(Brush brush, Brush border)
        {
            Context.DrawRectangle(brush, new Pen(border, 1), new Rect(12, 15 - 15, meterWidth,15 ));
        }

        private void DrawSignalMeter3(Brush brush, Brush border)

        {
            Context.DrawRectangle(brush, new Pen(border, 1), new Rect(8, 15 - 12, meterWidth, 12));
        }

        private void DrawSignalMeter2(Brush brush, Brush border)
        {
            Context.DrawRectangle(brush, new Pen(border, 1), new Rect(4, 15 - 9, meterWidth, 9));
        }

        private void DrawSignalMeter1(Brush brush, Brush border)
        {
            Context.DrawRectangle(brush, new Pen(border, 1), new Rect(0, 15 - 6, meterWidth, 6));
        }

        public void Dispose()
        {
            _drawingContext.Pop();
        }
    }
}